﻿using GDM.Hogar.Aplicacion.IoC.Resources;
using Microsoft.Practices.Unity;
using System;
using System.Runtime.Remoting.Messaging;
using System.ServiceModel;

namespace GDM.Hogar.Aplicacion.IoC.TiempoDeVida
{
    public sealed class TiempoVidaContextoEjecucionManager : LifetimeManager
    {
        private Guid _clave;

        public TiempoVidaContextoEjecucionManager()
            : this(Guid.NewGuid())
        {
        }

        private TiempoVidaContextoEjecucionManager(Guid clave)
        {
            if (clave == Guid.Empty)
            {
                throw new ArgumentException(Messages.PerExecutionContextLifetimeManagerKeyCannotBeNull);
            }

            _clave = clave;
        }

        public override object GetValue()
        {
            object resultado = null;

            if (OperationContext.Current != null)
            {
                var extensionContenedor = OperationContext.Current.Extensions.Find<ExtensionContenedor>();
                if (extensionContenedor != null)
                {
                    resultado = extensionContenedor.Value;
                }
            }
            else
            {
                resultado = CallContext.GetData(_clave.ToString());
            }

            return resultado;
        }

        public override void RemoveValue()
        {
            if (OperationContext.Current != null)
            {
                var extensionContenedor = OperationContext.Current.Extensions.Find<ExtensionContenedor>();
                if (extensionContenedor != null)
                {
                    OperationContext.Current.Extensions.Remove(extensionContenedor);
                }
            }
            else
            {
                CallContext.FreeNamedDataSlot(_clave.ToString());
            }
        }

        public override void SetValue(object newValue)
        {
            if (OperationContext.Current != null)
            {
                var extensionContenedor = OperationContext.Current.Extensions.Find<ExtensionContenedor>();
                if (extensionContenedor == null)
                {
                    extensionContenedor = new ExtensionContenedor
                    {
                        Value = newValue
                    };

                    OperationContext.Current.Extensions.Add(extensionContenedor);
                }
            }
            else
            {
                CallContext.SetData(_clave.ToString(), newValue);
            }
        }

        public class ExtensionContenedor : IExtension<OperationContext>
        {
            public object Value { get; set; }

            public void Attach(OperationContext owner)
            {
            }

            public void Detach(OperationContext owner)
            {
            }
        }
    }
}